/*
 * @Description:
 * @Version: 1.0
 * @Author: 琴时
 * @Date: 2021-08-30 17:02:41
 * @LastEditors: 琴时
 * @LastEditTime: 2021-09-02 15:30:24
 */

/**
 * @description: 变量类型判断
 * @param {type} [需要判断的类型]
 * @param {value} [需要判断的值]
 * @return {Boolean} [是否该类型]
 * @author: 琴时
 */
const IsType = (type, value) =>
  Object.prototype.toString.call(value) === `[object ${type}]`

/**
 * @description: 深拷贝变量-递归算法(recursive algorithm)
 * 支持 String,Number,Boolean,null,undefined,Object,Array,Date,RegExp,Error,Function 类型-进行深度拷贝
 * @param {params}  [需要深拷贝的变量]
 * @return {*} [靠背后的变量]]
 * @author: 琴时
 */
export const deepCopy = params => {
  const newValue = IsType('Object', params) // 判断是否是对象
    ? {}
    : IsType('Array', params) // 判断是否是数组
    ? []
    : IsType('Date', params) // 判断是否是日期对象
    ? new params.constructor(+params)
    : IsType('RegExp', params) || IsType('Error', params) // 判断是否是正则对象或错误对象
    ? new params.constructor(params)
    : params
  // 判断是否是数组或对象
  if (IsType('Object', params) || IsType('Array', params)) {
    // 循环遍历
    for (const key in params) {
      // 防止原型链的值
      Object.prototype.hasOwnProperty.call(params, key) &&
        (newValue[key] = deepCopy(params[key]))
    }
  }
  return newValue
}

/**
 * 测试用例
 * 将src/index.js底部执行函数:selectTest(params)的实参params改为2
 * 直接无法测试，请使用npm run dev或者去掉 export 使用node运行当前界面测试即可
 */
const obj = {
  a: '琴时',
  b: 1,
  c: true,
  d: null,
  e: undefined,
  f: { a: 1 },
  i: [1, 2, 3],
  j: new Date(),
  k: /^\d{6}$/,
  l: new Error(),
  m: function fn() {},
} // 需要被拷贝的对象
const obj2 = deepCopy(obj) // 拷贝的新对象
obj2.a = 'piante'
obj2.i[0] = 2
obj2.c = false
obj2.m = 1
obj2.j=new Date('2021-05-20')
obj2.l = 1
console.log('拷贝前:', obj)
console.log('拷贝后:', obj2)
